home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
Sherlock 2.0
/
DevLibSrc
/
Main_DevLib
/
LIBio.c
< prev
next >
Wrap
Text File
|
1995-11-16
|
9KB
|
489 lines
/*
devlib: ANSI Standard i/o module: this module calls only ANSI Standard functions.
source: LIBio.c
started: November 4, 1993.
version:
November 8, 1995.
Replaced error with err_error1-4.
July 10, 1994.
Added io_remove, io_rename, io_seek, io_write_buffer.
Added io_read_pad_all.
*/
#include <LIBlib.h>
#include <LIBio.h>
#include <LIBmem.h>
#include <LIBobj.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Define the size of the buffers allocated by io_create.
*/
#define IO_BUF_SIZE 1024
/*
The file status.
*/
typedef enum { IO_NULL, IO_CLOSED, IO_INPUT, IO_OUTPUT, IO_EOF } dummy;
/*
Define global statistics variables.
*/
long io_read_chars = 0; /* Chars read by io_read and io_read_all. */
long io_write_chars = 0; /* Chars written by io_write. */
long io_nl_count = 1; /* TRUE: number of consecutive newlines output. */
/*
Prototypes for local routines.
*/
static char * io_cvt_status (int status);
/*
Allocate a block of n bytes using lib_calloc.
*/
static void *
io_alloc(size_t n)
{
void * p = NULL;
/* Align. */
if (n & 1) {
n++;
}
p = lib_calloc( (size_t) 1, n);
if (p == NULL) {
char buf [100];
cvt_long(buf, 100, n);
err_fatal3("io_alloc: can not allocate ", buf, " bytes.");
}
return p;
}
/*
Close a file opened with io_open() or io_create().
Closing a NULL file is OK.
*/
void
io_close(io_file * file)
{
FTAG("io_close");
STATB(ftag);
if (file) {
ASSERT(
file -> io_file_path_name &&
(file -> io_file_status == IO_INPUT ||
file -> io_file_status == IO_OUTPUT ||
file -> io_file_status == IO_EOF));
/* Flush an output file. */
if (file -> io_file_status == IO_OUTPUT && file -> io_file_count > 0) {
io_write(file);
}
fclose(file -> io_file_file);
if (file -> io_file_buffer) {
lib_free(file -> io_file_buffer);
}
lib_free(file);
}
STATX(ftag);
}
/*
Open the file for writing only.
Return an io_file or NULL.
*/
io_file *
io_create(char * path_name, bool cant_flag, bool text_flag)
{
FTAG("io_create");
FILE * os_file = NULL;
io_file * file = NULL;
STATB(ftag);
ASSERT(path_name);
if (path_name[0] == '\0') {
if (cant_flag) {
err_error1("io_create: NULL file name");
}
STATX(ftag);
return NULL;
}
os_file = fopen(path_name, text_flag ? "w" : "wb");
if (os_file == NULL) {
if (cant_flag) {
err_error2("Can not create ", path_name);
}
STATX(ftag);
return NULL;
}
file = io_alloc(sizeof(io_file));
file -> io_file_path_name = path_name;
file -> io_file_file = os_file;
file -> io_file_status = IO_OUTPUT;
file -> io_file_buffer = io_alloc(IO_BUF_SIZE);
file -> io_file_bufsize = IO_BUF_SIZE;
file -> io_file_pointer = file -> io_file_buffer;
file -> io_file_count = 0;
STATX(ftag);
return file;
}
/*
Print the status of a stream.
*/
static char *
io_cvt_status(int status)
{
SL_DISABLE();
switch(status) {
case IO_NULL: return "IO_NULL";
case IO_CLOSED: return "IO_CLOSED";
case IO_INPUT: return "IO_INPUT";
case IO_OUTPUT: return "IO_OUTPUT";
case IO_EOF: return "IO_EOF";
default: return "Bad file status";
}
}
/*
Return the length of an open file or -1L.
*/
long
io_length(io_file * file)
{
FTAG("io_length");
long value = -1;
STATB(ftag);
ASSERT(file);
/* Seek to the end of the file. */
if (fseek(file -> io_file_file, 0, SEEK_END) != 0) {
goto error;
}
/* Get the value. */
value = ftell(file -> io_file_file);
if (value == -1) {
goto error;
}
/* Seek to the start of the file. */
fseek(file -> io_file_file, 0, SEEK_SET);
error:
done:
TRACEPX(ftag,
es(file -> io_file_path_name); eblank();
eret(); elong(value); enl());
return value;
}
/*
Open the file for reading only.
Return a pointer to the file stuct or NULL.
*/
io_file *
io_open(char * path_name, bool cant_flag, bool text_flag)
{
FTAG("io_open");
FILE * os_file = NULL;
io_file * file = NULL;
STATB(ftag);
ASSERT(path_name);
if (path_name[0] == '\0') {
if (cant_flag) {
err_error1("io_open: NULL file name");
}
goto done;
}
os_file = fopen(path_name, text_flag ? "r" : "rb");
if (os_file == NULL) {
if (cant_flag) {
err_error2("Can not open ", path_name);
}
goto done;
}
file = io_alloc(sizeof(io_file));
file -> io_file_path_name = path_name;
file -> io_file_file = os_file;
file -> io_file_status = IO_INPUT;
file -> io_file_buffer = NULL;
file -> io_file_pointer = NULL;
file -> io_file_count = 0;
file -> io_file_bufsize = 0;
done:
STATX(ftag);
return file;
}
/*
Read the indicated number of bytes into the buffer.
Return the number of bytes read.
*/
long
io_read (io_file * file, void * buffer, long n)
{
FTAG("io_read");
STATB(ftag);
ASSERT(file && buffer && n);
n = fread(buffer, 1, n, file -> io_file_file);
STATX(ftag);
return n;
}
/*
Read an entire file into a buffer.
Add one byte at end for a possible added newline.
*/
io_mem_block *
io_read_all(char * path_name, bool cant_flag, bool text_flag)
{
return io_read_pad_all(path_name, 0, ' ', 0, ' ', cant_flag, text_flag);
}
/*
Read an entire file into a padded buffer.
Add one byte at end for a possible added newline.
*/
io_mem_block *
io_read_pad_all(
char * path_name,
int lead_pad, char lead_char,
int trail_pad, char trail_char,
bool cant_flag, bool text_flag)
{
FTAG("io_read_pad_all");
register long length = 0; /* Length of file in bytes. */
register char * buffer = NULL;
register io_file * file = NULL;
register io_mem_block * result = NULL;
STATB(ftag);
file = io_open(path_name, cant_flag, text_flag);
if (file == NULL) {
goto error;
}
length = io_length(file);
if (length == -1L) {
goto error;
}
/* mem_freep points to the buffer so it can be deallocated later. */
obj_new_macro(buffer, length+lead_pad+trail_pad+1, "io read all buf");
{
long n = fread(buffer + lead_pad, 1, length, file -> io_file_file);
io_read_chars += n;
io_close(file);
if (n != length) {
goto error;
}
}
/*
Fill in the leading and trailing fields.
*/
{
register int i;
for (i = 0; i < lead_pad; i++) {
buffer[i] = lead_char;
}
for (i = 0; i < trail_pad; i++) {
buffer [length + lead_pad + i] = trail_char;
}
}
/*
End the buffer with a zero byte.
*/
buffer[length + lead_pad + trail_pad] = '\0';
obj_new_macro(result, sizeof(io_mem_block), "io_mem_block");
result -> mem_start = buffer + lead_pad;
result -> mem_length = length;
result -> mem_freep = buffer;
TRACEPX(ftag,
es(path_name); enl();
es("mem_start: "); eptr(buffer+lead_pad);
es(" mem_length: "); elong(length);
es(" mem_freep: "); eptr(buffer);
enl());
return result;
error:
TRACEPX(ftag, es("not found: "); es(path_name); enl());
return NULL;
}
/*
Remove (delete) the named file.
It should be close.
*/
void
io_remove(char * file_name)
{
FTAG("io_remove");
STATB(ftag);
remove(file_name);
STATX(ftag);
}
/*
Rename a file.
*/
void
io_rename(char * old_name, char * new_name)
{
rename(old_name, new_name);
}
/*
Seek to the indicated byte of the file.
Return IO_SEEK_OK if all went well.
*/
int
io_seek (io_file * file, long offset)
{
ASSERT(file);
return fseek(file -> io_file_file, offset, SEEK_SET);
}
/*
Print an io_file node.
*/
void
io_show_file(io_file * file)
{
FTAG("io_show_file");
STATB(ftag);
ASSERT(file);
#ifndef LIB_DONT_USE_ES
ecnl();
es("file: "); es(file -> io_file_path_name);
es(" at: "); eptr(file);
es(" status: "); es(io_cvt_status(file -> io_file_status));
ecnl();
es("buffer: "); eptr(file -> io_file_buffer);
es(" ptr: "); eptr(file -> io_file_pointer);
es(" count: "); elong(file -> io_file_count);
ecnl();
#endif
STATX(ftag);
}
/*
Write file -> io_file_count bytes from file -> io_file_buffer.
Reset the file buffer pointer and counts after the write.
Return the number of bytes written.
*/
long
io_write(register io_file * file)
{
FTAG("io_write");
size_t result = 0;
STATB(ftag);
ASSERT(file && file -> io_file_buffer && file -> io_file_count);
result = fwrite(
file -> io_file_buffer,
1, file -> io_file_count,
file -> io_file_file);
/*
We must not create *any* tracing output if es2os_flag is set!
(That would create a recursive call to io_write that would crash the stack.)
*/
#if 0 /* old code */
if (!es2os_flag) {
TRACEP(ftag,
es("file: "); eptr(file);
es(" buffer: "); eptr(file -> io_file_buffer);
es(" count: "); elong(file -> io_file_count); enl();
eret(); elong(result); enl());
}
#endif
/* Update these variables *after* printing the trace. */
file -> io_file_pointer = file -> io_file_buffer;
file -> io_file_count = 0;
io_write_chars += result;
STATX(ftag);
return result;
}
/*
Write n bytes from the buffer.
Return the number of bytes written.
*/
long
io_write_buffer(register io_file * file, void * buffer, long n)
{
FTAG("io_write");
size_t result = 0;
STATB(ftag);
ASSERT(file);
result = fwrite(buffer, 1, n, file -> io_file_file);
/*
We must not create *any* tracing output if es2os_flag is set!
(That would create a recursive call to io_write that would crash the stack.)
*/
#if 0 /* old code */
if (!es2os_flag) {
TRACEP(ftag,
es("file: "); eptr(file);
es(" buffer: "); eptr(file -> io_file_buffer);
es(" count: "); elong(file -> io_file_count); enl();
eret(); elong(result); enl());
}
#endif
io_write_chars += result;
STATX(ftag);
return result;
}